package impl.agentt.etudiant;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.logging.Logger;

import apps.BehTB;

import reservation.PlageHoraire;

import message.EDTMessage;
import message.presence.AcceptePlacement;
import message.presence.InitPresenceEtuAgent;
import message.presence.RefusPlacement;
import mysticedt.Behaviour;
import contraintes.ContrainteDispo;
import contraintes.Seance;
import debug.message.EtuDebugText;
import fr.irit.smac.may.lib.components.messaging.receiver.AgentRef;
import fr.irit.smac.may.lib.interfaces.Push;
import fr.irit.smac.may.lib.pmbehaviour.PatternMatchingBehavior;

public class BehaviourEtuImpl extends Behaviour {

	/**
	 * Liste des seances dans lesquelles l'etudiant veut s'inscrire.
	 */
	private ArrayList<Seance> listCours;
	/**
	 * Liste des indisponibilite de l'etudiant
	 */
	private ArrayList<ContrainteDispo> listIndisponibilite = new ArrayList<ContrainteDispo>();
	/**
	 * Table des agents pEtu, avec leur criticite.
	 */
	private Hashtable<AgentRef, Integer> listP = new Hashtable<AgentRef, Integer>();
	/**
	 * Criticite de l'agent etudiant.
	 */
	private int criticite = 0;
	
	PatternMatchingBehavior pmb = new PatternMatchingBehavior(this);

	public void defaultCase(Object message) {
		Logger log = Logger.getLogger("alerte");
		log.info("Alerte par "+this.getClass().getCanonicalName()+" : Incomprehension du message "+message.getClass().getCanonicalName());
	}
	
	/**
	 * Reception d'une demande d'initialisation
	 * - recuperation de sa liste de seances
	 * - creation de ses agents pEtu
	 */
	public void caseInitEtudiantAgent() {
		this.listCours = subscriptionAccess().getListIdCoursEtu();
		
		this.listP = new Hashtable<AgentRef, Integer>();
		for (Iterator<Seance> itr = listCours.iterator(); itr.hasNext();) {
			AgentRef pEtuRef = createPresenceAgent().createPresenceEtudiantAgent();
			debugText("Creation %s : OK",pEtuRef.getName());
			listP.put(pEtuRef,0);
			//Demande a l'agent pEtu de s'initialiser
			send().send(new InitPresenceEtuAgent(itr.next(), myRef().pull()), pEtuRef);
			//Pour le moment la criticite correspond au nombre de ses agents pEtu non satisfait
			criticite++;
		}
		debugText("Initialisation : OK");
	}

	/**
	 * Reception d'une notification exprimant le fait qu'un agent pEtu est place
	 *  
	 * @param a
	 */
	public void casePresencePlacee(AgentRef exp, PlageHoraire pH) {
		Boolean valide = true;
		//Verif
		Iterator<ContrainteDispo> iteCDisp = listIndisponibilite.iterator();
		while(iteCDisp.hasNext()) {
			if(BehTB.plageHoraireIsInContrainteDispo(pH,iteCDisp.next())) {
				debugText("Placement de %s : Impossible",exp.getName());
				send().send(new RefusPlacement(listIndisponibilite), exp);
				valide = false;
				break;
			}
		}
		if(valide) {
			send().send(new AcceptePlacement(), exp);
			debugText("Placement de %s : OK",exp.getName());
			criticite--;
			listP.put(exp,0);
			if(criticite==0){
				debugText("Inscription a tous mes cours : OK");
			}
		}
	}

	/**
	 * Reception d'une notification exprimant le fait qu'un agent pEtu n'est plus place
	 * 
	 * @param a
	 */
	public void casePresenceDeplacee(AgentRef a, Integer i) {
		listP.put(a, i);
		criticite++;
	}

	/**
	 * Reception de la criticite d'un agent pEtu
	 * 
	 * @param a
	 */
	public void casePresenceCrit(AgentRef a, Integer i) {
		listP.put(a, i);
	}

	/**
	 * L'inteface cycle demande au PatternMatching d'appeler la bonne méthode
	 * en fonction du type du message.
	 */
	@Override
	protected Push<EDTMessage> cycle() {
		return new Push<EDTMessage>() {
			public void push(EDTMessage message) {
				pmb.match(message);
			}

		};
	}

	protected void debugText(String s , Object... params){
		if(debug().isDebugON()){
			debug().sendDebugMessage(new EtuDebugText(myRef().pull(),String.format(s, params)));
		}
	}
}
